//
//  SSChristmas.m
//  Secret Santa
//
//  Created by Andrew Cain on 12/10/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import <Message/NSMailDelivery.h>
#import "SSChristmas.h"
#import "SSPerson.h"

@implementation SSChristmas

- (void) dealloc
{
	[[NSNotificationCenter defaultCenter] removeObserver: self];
	[super dealloc];
}

- (NSString *)message 
{
    NSString * tmpValue;
    
    [self willAccessValueForKey: @"message"];
    tmpValue = [self primitiveValueForKey: @"message"];
    [self didAccessValueForKey: @"message"];
    
    return tmpValue;
}

- (void)setMessage:(NSString *)value 
{
    [self willChangeValueForKey: @"message"];
    [self setPrimitiveValue: value forKey: @"message"];
    [self didChangeValueForKey: @"message"];
}

- (NSString *)title 
{
    NSString * tmpValue;
    
    [self willAccessValueForKey: @"title"];
    tmpValue = [self primitiveValueForKey: @"title"];
    [self didAccessValueForKey: @"title"];
    
    return tmpValue;
}

- (void)setTitle:(NSString *)value 
{
    [self willChangeValueForKey: @"title"];
    [self setPrimitiveValue: value forKey: @"title"];
    [self didChangeValueForKey: @"title"];
}

- (BOOL)validateTitle: (id *)valueRef error:(NSError **)outError 
{
    // Insert custom validation logic here.
    return YES;
}

- (BOOL)validateMessage: (id *)valueRef error:(NSError **)outError 
{
    // Insert custom validation logic here.
    return YES;
}

- (NSString *)year 
{
    NSString * tmpValue;
    
    [self willAccessValueForKey: @"year"];
    tmpValue = [self primitiveValueForKey: @"year"];
    [self didAccessValueForKey: @"year"];
    
    return tmpValue;
}

- (void)setYear:(NSString *)value 
{
    [self willChangeValueForKey: @"year"];
    [self setPrimitiveValue: value forKey: @"year"];
    [self didChangeValueForKey: @"year"];
}

- (BOOL)validateYear: (id *)valueRef error:(NSError **)outError 
{
    // Insert custom validation logic here.
    return YES;
}

- (NSNumber *)prepared 
{
    NSNumber * tmpValue;
    
    [self willAccessValueForKey: @"prepared"];
    tmpValue = [self primitiveValueForKey: @"prepared"];
    [self didAccessValueForKey: @"prepared"];
    
    return tmpValue;
}

- (void)setPrepared:(NSNumber *)value 
{
    [self willChangeValueForKey: @"prepared"];
    [self setPrimitiveValue: value forKey: @"prepared"];
    [self didChangeValueForKey: @"prepared"];
}

- (BOOL)validatePrepared: (id *)valueRef error:(NSError **)outError 
{
    // Insert custom validation logic here.
    return YES;
}


- (void)addPeopleObject:(SSPerson *)value 
{    
    NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
    
    [self willChangeValueForKey:@"people" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
    
    [[self primitiveValueForKey: @"people"] addObject: value];
    
    [self didChangeValueForKey:@"people" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
    
    [changedObjects release];
}

- (void)removePeopleObject:(SSPerson *)value 
{
    NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
    
    [self willChangeValueForKey:@"people" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
    
    [[self primitiveValueForKey: @"people"] removeObject: value];
    
    [self didChangeValueForKey:@"people" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
    
    [changedObjects release];
}

- (void) addPeople: (NSSet *) peopleToAdd
{
	[self willChangeValueForKey:@"people"
				withSetMutation:NSKeyValueUnionSetMutation
				   usingObjects:peopleToAdd];
	
    [[self primitiveValueForKey:@"people"] unionSet:peopleToAdd];
	
    [self didChangeValueForKey:@"people"
			   withSetMutation:NSKeyValueUnionSetMutation
				  usingObjects:peopleToAdd];
}

- (void) removePeople: (NSSet *) peopleToRemove
{
	[self willChangeValueForKey:@"people"
				withSetMutation:NSKeyValueMinusSetMutation
				   usingObjects:peopleToRemove];
	
    [[self primitiveValueForKey:@"people"] minusSet:peopleToRemove];
	
    [self didChangeValueForKey:@"people"		
			   withSetMutation:NSKeyValueMinusSetMutation		
				  usingObjects:peopleToRemove];
}

- (void)awakeFromInsert
{
	[super awakeFromInsert];
	
	NSCalendarDate *now = [NSCalendarDate calendarDate];	
	[self setYear: [NSString stringWithFormat:@"%d", [now yearOfCommonEra]]];	
	
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(contextChanged:)
												 name:NSManagedObjectContextObjectsDidChangeNotification
											   object:nil];
}


- (void) contextChanged: (NSNotification *) notification
{
	if([[self prepared] boolValue])
	{
		if([[notification userInfo] objectForKey:NSInsertedObjectsKey] || [[notification userInfo] objectForKey: NSDeletedObjectsKey])
		{
			[self setPrepared: [NSNumber numberWithBool: NO]];
		}
	}
}

- (BOOL) prepareMatches
{
	NSArray *people = [[self primitiveValueForKey:@"people"] allObjects];	
	SSPerson *p;
	
	//HACK: Just try brute force... it should work as long as restrictions are "sensible"
	
	int tries;
	BOOL done = NO;
	
	for(tries = 0; tries < 100 && ! done; tries++)
	{
		NSLog(@"Attempting to find matches for all people... attempt %d", tries + 1);
		
		//prepare available people set
		NSMutableArray *availablePeople = [NSMutableArray arrayWithArray: people];
		NSEnumerator *iter = [people objectEnumerator];	
		
		//sort to have most restricted person first
		[availablePeople sortUsingSelector:@selector(compare:)];
		
		//assume done...
		done = YES;
		
		//for each person
		while( done && (p = [iter nextObject]))
		{
			NSLog(@"Preparing %@", [p name]);
			
			done = done && [p findMatchFrom: availablePeople];
		}
	}
	
	return done;
}

- (void) sendEmailWithStatus: (id <StatusMessageDelegate>)status;
{
	NSArray *people = [[self primitiveValueForKey:@"people"] allObjects];	
	NSEnumerator *iter = [people objectEnumerator];	
	SSPerson *p;
	
	[status setIncrementCountTo: [people count]];
	
	NSMutableString *body;
	
	body = [NSMutableString stringWithString:[self message]];
	
	[body replaceOccurrencesOfString: @"{title}" 
						  withString: [self title] 
							 options: NSCaseInsensitiveSearch
							   range: NSMakeRange(0, [body length]) ];
	
	[body replaceOccurrencesOfString: @"{year}" 
						  withString: [self year] 
							 options: NSCaseInsensitiveSearch
							   range: NSMakeRange(0, [body length]) ];
	
	while( p = [iter nextObject] )
	{
		NSLog(@"Sending email to %@", [p name]);
		
		[status addStatus: [NSString stringWithFormat:@"Sending email to %@", [p name]]];
		[status changeStatus: 
			[p sendEmailWithMessage: body withTitle: [self title]]];
		
		[status incrementProgress];
	}
}

@end
